// vector2.h
// Written by Sergei Sokov

#ifndef __VECTOR2_H
#define __VECTOR2_H

#include "3d/tuple2.h"
#include <math.h>  // sqrt()
#include "geom.h"  // DIV_MIN_FLOAT

template<class T>
class Vector2_ : public Tuple2_<T> {
 public:
  // Constructors
  Vector2_(void) {}
  Vector2_(const Vector2_ &t) { x=t.x; y=t.y; }
  Vector2_(const T *v) { x=v[0]; y=v[1]; }
  Vector2_(T xx, T yy) { x=xx; y=yy; }

  T lengthSquared(void) const {
    return x*x + y*y;
  }

  T length(void) const {
    return (T)sqrt( x*x + y*y );
  }

  T dot(const Tuple2_<T> &v) const { 
    return x*v.x + y*v.y; 
  }
  T dot(T *v) const { 
    return x*v[0] + y*v[1]; 
  }
  T dot(T xx, T yy) const {
    return x*xx + y*yy; 
  }
  static T dot(T *a, T *b) {
    return a[0]*b[0] + a[1]*b[1];
  }

  T crossLen(const Tuple2_<T> &v) const {
    return x*v.y - y*v.x;
  }

  static T crossLen(const Tuple2_<T> &v1, const Tuple2_<T> &v2) {
    return v1.x*v2.y - v1.y*v2.x;
  }

  void normalize(void) {
    T s = 1.0f/length();
    x *= s; y *= s;
  }

  void normalize(T f) {
    T s = f/length();
    x *= s; y *= s;
  }

  void normalize(const Vector2_ &v) {
    T s = 1.0f/v.length();
    x=v.x*s; y=v.y*s;
  }

  int normalizeSafe(void) {
    T s = length();
    if(s<=0.0f) {
      x=y=0.0f;
      return 0;
    }
    s = 1.0f/s;
    x *= s; y *= s;
    return 1;
  }

  int normalizeSafe(const Vector2_ &v) {
    T s = v.length();
    if(s<=0.0f) {
      x=y=0.0f;
      return 0;
    }
    s = 1.0f/s;
    x=v.x*s; y=v.y*s;
    return 1;
  }

  T angleCos(const Vector2_ &v2) const {
    T mulL = length() * v2.length();
    if(mulL < DIV_MIN_FLOAT)
      return 1.0f;  // 0 graduces
    return dot(v2)/mulL;
  }

  void rotate( T cosA, T sinA ) {
    set( cosA*x - sinA*y,
         sinA*x + cosA*y );
  }
};

/*
 * Dot product.
 */

template <class T>
inline T operator&(const Tuple2_<T>& a, const Tuple2_<T>& b) {
  return a.x*b.x + a.y*b.y;
}


typedef Vector2_<float>  Vector2f;
typedef Vector2_<double> Vector2d;

#endif

/* eof */
